package com.morning.common.util;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @description：图片通用处理工具类
 * @author CXX
 * @version 创建时间：2016年8月19日  上午11:17:00
 */
public class ImageUtils {
	
	private static Logger logger = LoggerFactory.getLogger(ImageUtils.class);
	
	/**
     * 使用ImageReader获取图片尺寸
     * 
     * @param src 源图片路径
     */
    public void getImageSizeByImageReader(String src) {
        long beginTime = new Date().getTime();
        File file = new File(src);
        try {
            Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
            ImageReader reader = (ImageReader) readers.next();
            ImageInputStream iis = ImageIO.createImageInputStream(file);
            reader.setInput(iis, true);
            System.out.println("width:" + reader.getWidth(0));
            System.out.println("height:" + reader.getHeight(0));
        } catch (IOException e) {
        	logger.error("ImageUtils.getImageSizeByImageReader", e);
        }
        long endTime = new Date().getTime();
        System.out.println("使用[ImageReader]获取图片尺寸耗时：[" + (endTime - beginTime)+"]ms");
    }

    /**
     * 使用BufferedImage获取图片尺寸
     * 
     * @param src 源图片路径
     */
    public void getImageSizeByBufferedImage(String src) {
        long beginTime = new Date().getTime();
        File file = new File(src);
        FileInputStream is = null;
        try {
            is = new FileInputStream(file);
        } catch (FileNotFoundException e) {
        	logger.error("ImageUtils.getImageSizeByImageReader", e);
        }
        BufferedImage sourceImg = null;
        try {
            sourceImg = javax.imageio.ImageIO.read(is);
            System.out.println("width:" + sourceImg.getWidth());
            System.out.println("height:" + sourceImg.getHeight());
        } catch (IOException e1) {
        	logger.error("ImageUtils.getImageSizeByImageReader", e1);
        }
        long endTime = new Date().getTime();
        System.out.println("使用[BufferedImage]获取图片尺寸耗时：[" + (endTime - beginTime)+"]ms");
    }

    /**
     * 获取图片的宽
     * @param srcImageFile 源图片路径
     * @return
     */
    public static int  getImageWidth(String srcImageFile){
         try {
        	 File file = new File(srcImageFile);
             Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
             ImageReader reader = (ImageReader) readers.next();
             ImageInputStream iis = ImageIO.createImageInputStream(file);
             reader.setInput(iis, true);
             return reader.getWidth(0);
         } catch (IOException e) {
             e.printStackTrace();
             return 0;
         }
    }
    
    /***
     * 获取图片的高
     * @param srcImageFile 源图片路径
     * @return
     * @date   2016-3-30下午9:02:19
     */
    public static int getImageHeight(String srcImageFile){
    	File file = new File(srcImageFile);
        try {
            Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
            ImageReader reader = (ImageReader) readers.next();
            ImageInputStream iis = ImageIO.createImageInputStream(file);
            reader.setInput(iis, true);
           
            return reader.getHeight(0);
        } catch (IOException e) {
            e.printStackTrace();
            return 0;
        }
    }
       
	 /**
	  * 图片旋转指定角度 
	  * @param src 文件流:源图像地址
	  * @param angel 旋转度
	  * @return
	  */
	 public static BufferedImage Rotate(Image src, int angel) {  
	        int src_width = src.getWidth(null);   // 源图宽度  
	        int src_height = src.getHeight(null);   // 源图高度  
	        angel=angel>0?angel:(360+angel); 
	        Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(  
	                src_width, src_height)), angel);  
	  
	        BufferedImage res = null;  
	        res = new BufferedImage(rect_des.width, rect_des.height,  
	                BufferedImage.TYPE_INT_RGB);  
	        Graphics2D g2 = res.createGraphics();  
	        g2.setPaint(Color.WHITE);
	        g2.fillRect(0, 0, rect_des.width,  rect_des.height);
	        // transform  
	        g2.translate((rect_des.width - src_width) / 2,  
	                (rect_des.height - src_height) / 2);  
	        g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);  
	  
	        g2.drawImage(src, null, null);  
	        return res;  
	 }
	 public static Rectangle CalcRotatedSize(Rectangle src, int angel) {  
         // if angel is greater than 90 degree, we need to do some conversion  
         if (angel >= 90) {  
             if(angel / 90 % 2 == 1){  
                 int temp = src.height;  
                 src.height = src.width;  
                 src.width = temp;  
             }  
             angel = angel % 90;  
         }  
         double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;  
         double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;  
         double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;  
         double angel_dalta_width = Math.atan((double) src.height / src.width);  
         double angel_dalta_height = Math.atan((double) src.width / src.height);  
   
         int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha  
                 - angel_dalta_width));  
         int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha  
                 - angel_dalta_height));  
         int des_width = src.width + len_dalta_width * 2;  
         int des_height = src.height + len_dalta_height * 2;  
         return new java.awt.Rectangle(new Dimension(des_width, des_height));  
    }
    
	/***
	 * 剪裁图片
	 * @param srcImageFile
	 * @param dest
	 * @param x  起点横坐标
	 * @param y  纵坐标
	 * @param w  长
	 * @param h  高
	 * @throws IOException
	 * @date   2016-3-30下午12:19:10
	 */
	 public static boolean cutImage(InputStream srcImageFile,File dest,int x,int y,int w,int h) {   
         try{
        	 BufferedImage src = ImageIO.read(srcImageFile); // 读入文件
			 Iterator<ImageReader> iterator = ImageIO.getImageReadersByFormatName("jpg");   
	         ImageReader reader = (ImageReader)iterator.next();  
	         
	        //获取图片流   
	         ByteArrayOutputStream bs = new ByteArrayOutputStream();  
	         ImageOutputStream ios = ImageIO.createImageOutputStream(bs);  
	         ImageIO.write(src, "jpg", ios);
	         InputStream in=new  ByteArrayInputStream(bs.toByteArray());
	         ImageInputStream iis = ImageIO.createImageInputStream(in);   
	         reader.setInput(iis, true); 
	         ImageReadParam param = reader.getDefaultReadParam(); 
	         x=(x>0?x:0);
	         y=(y>0?y:0);
	         Rectangle rect = new Rectangle(x, y, w,h);    
	         param.setSourceRegion(rect);   
	         BufferedImage bi = reader.read(0,param);     
	         ImageIO.write(bi, "jpg", dest);    
	         return true;
         }catch (Exception e) {
        	 e.printStackTrace();
        	 return false;
		}
    }
    
	/**
	 * 剪裁图片(x,y,w,h,r)    
	 * @param srcImageFile 文件流:源图像地址
	 * @param dest   新图像
	 * @param x  目标切片起点x坐标 
	 * @param y  目标切片起点y坐标 
	 * @param w  目标切片宽度
	 * @param h  目标切片高度 
	 * @param r  目标切片旋转度
	 * @return
	 */
	public static boolean cutAndRotateImage(InputStream srcImageFile,File dest,int x,int y,int w,int h,int r){
		try{
			/*
			 * BufferedImage是Image的一个子类，BufferedImage生成的图片在内存里有一个图像缓冲区，
			 * 利用这个缓冲区我们可以很方便的操作这个图片，通常用来做图片修改操作如大小变换、图片变灰、设置图片透明或不透明等。
			 */
			BufferedImage src = ImageIO.read(srcImageFile); // 读入文件
	
	        //图片旋转指定角度 
			BufferedImage tag= Rotate(src, r);
			
			//读取图片文件 
			Iterator<ImageReader> iterator = ImageIO.getImageReadersByFormatName("jpg");   
	        ImageReader reader = (ImageReader)iterator.next(); 
	        
	        //获取图片流   
	        ByteArrayOutputStream bs = new ByteArrayOutputStream();  
	        ImageOutputStream ios = ImageIO.createImageOutputStream(bs);  
	        ImageIO.write(tag, "jpg", ios);
	        InputStream in=new  ByteArrayInputStream(bs.toByteArray());
	        ImageInputStream iis=ImageIO.createImageInputStream(in);
	        reader.setInput(iis, true);   
	        ImageReadParam param = reader.getDefaultReadParam(); 
	        x=(x>0?x:0);
	        y=(y>0?y:0);
	        
	        //定义一个矩形 
	        Rectangle rect = new Rectangle(x, y, w,h);    
	        
	        //提供一个 BufferedImage，将其用作解码像素数据的目标。   
	        param.setSourceRegion(rect);   
	        BufferedImage bi = reader.read(0,param);    
	        
	        //保存新图片  
	        ImageIO.write(bi, "jpg", dest);  
			return true;
		}catch (Exception e) {
			return false;
		}
	}

	 /***
	  * 按照比例缩放
	  * @param srcImageFile
	  * @param result  
	  * @param scale 缩放比例
	  * @param flag 缩放选择:true 放大; false 缩小;
	  * @return
	  * @date   2016-3-30下午2:39:44
	  */
	 public  static boolean scale(String srcImageFile, String result,int scale, boolean flag) {
	        try {
	        	File file = new File(srcImageFile);
	            BufferedImage src = ImageIO.read(file); // 读入文件
	             Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
	             ImageReader reader = (ImageReader) readers.next();
	             ImageInputStream iis = ImageIO.createImageInputStream(file);
	             reader.setInput(iis, true);
	            int width = reader.getWidth(0); // 得到源图宽
	            int height = reader.getHeight(0); // 得到源图长
	            if (flag) {// 放大
	                width = width * scale;
	                height = height * scale;
	            } else {// 缩小
	                width = width / scale;
	                height = height / scale;
	            }
	            Image image = src.getScaledInstance(width, height,
	                    Image.SCALE_DEFAULT);
	            BufferedImage tag = new BufferedImage(width, height,
	                    BufferedImage.TYPE_INT_RGB);
	            Graphics g = tag.getGraphics();
	            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
	            g.dispose();
	            ImageIO.write(tag, "jpg", new File(result));// 输出到文件流
	            return true;
	        } catch (IOException e) {
	            e.printStackTrace();
	            return false;
	        }
	    }
	 
	/***
	 * 缩放图像，按照长宽缩放
	 * @param srcImageFile
	 * @param result
	 * @param height  变换后的高度
	 * @param width   变换后的长度
	 * @param bb      比例不对称时，是否补白，true 补白;false 不补白
	 * @return
	 * @date   2016-3-30下午2:44:37
	 */
	public static boolean scale2(String srcImageFile, String result, int height, int width, boolean bb) {
	    try {
	    	
	        double ratio = 0.0; // 缩放比例
	        File file = new File(srcImageFile);
	        BufferedImage bi = ImageIO.read(file); // 读入文件
	        Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
	        ImageReader reader = (ImageReader) readers.next();
	        ImageInputStream iis = ImageIO.createImageInputStream(file);
	        reader.setInput(iis, true);
	        int width1 = reader.getWidth(0); // 得到源图宽
	        int height1 = reader.getHeight(0); // 得到源图长
	        @SuppressWarnings("static-access")
			Image itemp = bi.getScaledInstance(width, height, bi.SCALE_SMOOTH);
	        // 计算比例
	        if ((height1 > height) || (width1 > width)) {
	            if (height1 > width1) {
	                ratio = (new Integer(height)).doubleValue()
	                        / height1;
	            } else {
	                ratio = (new Integer(width)).doubleValue() / width1;
	            }
	            AffineTransformOp op = new AffineTransformOp(AffineTransform
	                    .getScaleInstance(ratio, ratio), null);
	            itemp = op.filter(bi, null);
	        }
	        if (bb) {//补白
	            BufferedImage image = new BufferedImage(width, height,
	                    BufferedImage.TYPE_INT_RGB);
	            Graphics2D g = image.createGraphics();
	            g.setColor(Color.white);
	            g.fillRect(0, 0, width, height);
	            if (width == itemp.getWidth(null))
	                g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2,
	                        itemp.getWidth(null), itemp.getHeight(null),
	                        Color.white, null);
	            else
	                g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0,
	                        itemp.getWidth(null), itemp.getHeight(null),
	                        Color.white, null);
	            g.dispose();
	            itemp = image;
	        }
	        ImageIO.write((BufferedImage) itemp, "JPEG", new File(result));
	        return true;
	    } catch (IOException e) {
	        e.printStackTrace();
	        return false;
	    }
	}
	 
	 /***
	  * 转换图像格式
	  * @param srcImageFile 原图像地址
	  * @param formatName   转换类型
	  * @param destImageFile 转换后的地址
	  * @return
	  * @author roychenyi
	  * @date   2016-3-30下午2:49:15
	  */
	public  static boolean convert(String srcImageFile, String formatName, String destImageFile) {
	    try {
	        File f = new File(srcImageFile);
	        f.canRead();
	        f.canWrite();
	        BufferedImage src = ImageIO.read(f);
	        ImageIO.write(src, formatName, new File(destImageFile));
	        return true;
	    } catch (Exception e) {
	        e.printStackTrace();
	        return false;
	    }
	}
	    
	/**
	 * 彩色转为黑白 
	 * @param srcImageFile 源图像地址
	 * @param destImageFile 目标图像地址
	 */
	public final static void gray(String srcImageFile, String destImageFile) {
	    try {
	        BufferedImage src = ImageIO.read(new File(srcImageFile));
	        ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
	        ColorConvertOp op = new ColorConvertOp(cs, null);
	        src = op.filter(src, null);
	        ImageIO.write(src, "jpg", new File(destImageFile));
	    } catch (IOException e) {
	        e.printStackTrace();
	    }
	}
	    
	/**
	 * 给图片添加图片水印
	 * @param pressImg 水印图片
	 * @param srcImageFile 源图像地址
	 * @param destImageFile 目标图像地址
	 * @param x 修正值。 默认在中间
	 * @param y 修正值。 默认在中间
	 * @param alpha 透明度：alpha 必须是范围 [0.0, 1.0] 之内（包含边界值）的一个浮点数字
	 */
	public  static boolean pressImage(String pressImg, String srcImageFile,String destImageFile,
	        int x, int y, float alpha) {
	    try {
	    	File file = new File(srcImageFile);
	        BufferedImage src = ImageIO.read(file); // 读入文件
	         Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
	         ImageReader reader = (ImageReader) readers.next();
	         ImageInputStream iis = ImageIO.createImageInputStream(file);
	         reader.setInput(iis, true);
	        int width = reader.getWidth(0); // 得到源图宽
	        int height = reader.getHeight(0); // 得到源图长
	        BufferedImage image = new BufferedImage(width, height,
	                BufferedImage.TYPE_INT_RGB);
	        Graphics2D g = image.createGraphics();
	        g.drawImage(src, 0, 0, width, height, null);
	        // 水印文件
	        Image src_biao = ImageIO.read(new File(pressImg));
	        int wideth_biao = src_biao.getWidth(null);
	        int height_biao = src_biao.getHeight(null);
	        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
	                alpha));
	        g.drawImage(src_biao, (width-wideth_biao-x) ,
	                (height-height_biao-y) , wideth_biao, height_biao, null);
	        // 水印文件结束
	        g.dispose();
	        ImageIO.write((BufferedImage) image,  "jpg", new File(destImageFile));
	        return true;
	    } catch (Exception e) {
	        e.printStackTrace();
	        return false;
	    }
	}
	    
	/**
	 * 给图片添加文字水印
	 * @param pressText 水印文字
	 * @param srcImageFile 源图像地址
	 * @param destImageFile 目标图像地址
	 * @param fontName 水印的字体名称
	 * @param fontStyle 水印的字体样式
	 * @param color 水印的字体颜色
	 * @param fontSize 水印的字体大小
	 * @param x 修正值
	 * @param y 修正值
	 * @param alpha 透明度：alpha 必须是范围 [0.0, 1.0] 之内（包含边界值）的一个浮点数字
	 */
	public  static boolean pressText(String pressText,
	        String srcImageFile, String destImageFile, String fontName,
	        int fontStyle, Color color, int fontSize,int x,
	        int y, float alpha) {
	    try {
	    	File file = new File(srcImageFile);
	        BufferedImage src = ImageIO.read(file); // 读入文件
	         Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
	         ImageReader reader = (ImageReader) readers.next();
	         ImageInputStream iis = ImageIO.createImageInputStream(file);
	         reader.setInput(iis, true);
	        int width = reader.getWidth(0); // 得到源图宽
	        int height = reader.getHeight(0); // 得到源图长
	        BufferedImage image = new BufferedImage(width, height,
	                BufferedImage.TYPE_INT_RGB);
	        Graphics2D g = image.createGraphics();
	        g.drawImage(src, 0, 0, width, height, null);
	        g.setColor(color);
	        g.setFont(new Font(fontName, fontStyle, fontSize));
	        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
	                alpha));
	        // 在指定坐标绘制水印文字
	        g.drawString(pressText, (width - (getLength(pressText) * fontSize))
	                / 2 + x, (height - fontSize) / 2 + y);
	        g.dispose();
	        ImageIO.write(image, "jpg", new File(destImageFile));// 输出到文件流
	        return true;
	    } catch (Exception e) {
	        e.printStackTrace();
	        return false;
	    }
	}
	    
	/**
	 * 计算text的长度（一个中文算两个字符）
	 * @param text
	 * @return
	 */
	public  static int getLength(String text) {
	    int length = 0;
	    for (int i = 0; i < text.length(); i++) {
	        if (new String(text.charAt(i) + "").getBytes().length > 1) {
	            length += 2;
	        } else {
	            length += 1;
	        }
	    }
	    return length / 2;
	}
}
